﻿using DH.Core;
using DH.Core.Exceptions;
using DH.Core.MapperEx.DataContractMapper;
using DH.Core.MapperHelper;
using DH.Core.UI.ViewModel;
using DH.Service;
using DH.Service.Domain.User;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using System.Security.Claims;

namespace DH.Web.Controllers
{
    public abstract class CrudControllerBase<TCodeTabelEntity, TCodeTabelModel, Tkey> : ControllerBase
        where TCodeTabelEntity : BaseEntity<Tkey>, new()
        where TCodeTabelModel : EntityModelBase<Tkey>, new()
    {
        protected readonly BaseService<TCodeTabelEntity, Tkey> _baseService;
        /// <summary>
        /// 数据转换器
        /// </summary>
        protected ICrudDtoMapper<TCodeTabelEntity, TCodeTabelModel, Tkey> CrudDtoMapper { get; set; }


        protected CrudControllerBase(IServiceCollection serviceCollection,
                                    BaseService<TCodeTabelEntity,Tkey> baseService
                                    ) :base(serviceCollection)
        {
            _baseService = baseService;
            CrudDtoMapper = serviceCollection.BuildServiceProvider().GetService<ICrudDtoMapper<TCodeTabelEntity, TCodeTabelModel, Tkey>>() as BaseCrudDtoMapper<TCodeTabelEntity, TCodeTabelModel, Tkey>;
            //_baseService = serviceCollection.BuildServiceProvider().GetService<BaseService<TCodeTabelEntity, Tkey>>();
        }

        #region 不带action 的异步操作 
        //[HttpGet("{id}")]
        //public async Task<IActionResult> GetAsync(Tkey id)
        //{
        //    Guard.CheckArgumentNull(CrudDtoMapper, "数据转换器不能为空");
        //    try
        //    {
        //        TCodeTabelModel model;
        //        var tableEntity = await _baseService.GetAsync(id);
        //        if (tableEntity == null)
        //        {
        //            return NotFoundResult($"Code with id {id} not found in {nameof(TCodeTabelModel)}.");
        //        }
        //        model = CrudDtoMapper.MapEntityToDto(tableEntity);

        //        return OkResult(model.ToJson());
        //    }
        //    catch (Exception ex)
        //    {
        //        return InternalServerError(ex, "Error while loading {0} with id '{1}'", nameof(TCodeTabelModel), id);
        //    }

        //}
        [HttpGet()]
        public async Task<IActionResult> GetAllAsync()
        {
            Guard.CheckArgumentNull(CrudDtoMapper, "数据转换器不能为空");
            try
            {
                IEnumerable<TCodeTabelModel> models;
                var tableEntitys = await _baseService.GetAllAsync();
                models = tableEntitys.Select(c=> {
                    return CrudDtoMapper.MapEntityToDto(c);
                });

                return OkResult(models.ToJson());
            }
            catch (Exception ex)
            {
                return InternalServerError(ex, "Error while loading {0}", nameof(TCodeTabelModel));
            }
        }
        [HttpPost]
        public async Task<IActionResult> PostAsync(TCodeTabelModel model)
        {
            if (!ModelState.IsValid)
            {
                return BadRequestResult(ModelState);
            }
            Guard.CheckArgumentNull(CrudDtoMapper, "数据转换器不能为空");

            try {
                ///dto 转entity
                var entity = CrudDtoMapper.MapDtoToEntity(model);

                var insertedEntity = await _baseService.InsertAsync(entity);

                return Success("更新成功!", CrudDtoMapper.MapEntityToDto(insertedEntity, model));
            }
            catch (ValidationException validationEx)
            {
                return BadRequestResult(validationEx);
            }
            catch (Exception ex)
            {
                return InternalServerError(ex, "Error while inserting {0}", nameof(TCodeTabelModel));
            }
            

        }

        [HttpPut("{id}")]
        public async Task<IActionResult> UpdateAsync(Tkey id,TCodeTabelModel model)
        {
            if (!ModelState.IsValid)
            {
                return BadRequestResult(ModelState);
            }
            Guard.CheckArgumentNull(CrudDtoMapper, "数据转换器不能为空");

            try {
                if (model == null) throw new ValidationException("model not provided");
                if (!id.Equals(model.Id)) throw new ValidationException("id does not match model id");
                var oldEntity = await _baseService.GetAsync(id);
                if (oldEntity==null)
                {
                    return NotFoundResult($"Code with id {id} not found in {nameof(TCodeTabelModel)}.");
                }
                var newEntity = CrudDtoMapper.MapDtoToEntity(model);
                await _baseService.UpdateAsync(newEntity);

                return Success("更新成功！");
            }
            catch (EntityNotFoundException)
            {
                return NotFoundResult("No event found with id {0}", id);
            }
            catch (ValidationException validationEx)
            {
                return BadRequestResult(validationEx);
            }
            catch (Exception ex)
            {
                return InternalServerError(ex, "Error while updating {0}", nameof(TCodeTabelModel));
            }

        }


        [HttpDelete("{id}")]
        public async Task<IActionResult> DeleteAsync(Tkey id)
        {
            Guard.CheckArgumentNull(CrudDtoMapper, "数据转换器不能为空");

            try {
                await _baseService.DeleteAsync(id);

                return Success("删除成功！");
            }
            catch (EntityNotFoundException)
            {
                return NotFoundResult("No event found with id {0}", id);
            }
            catch (ValidationException validationEx)
            {
                return BadRequestResult(validationEx);
            }
            catch (Exception ex)
            {
                return InternalServerError(ex, "Error while deleting {0}", nameof(TCodeTabelModel));
            }
        }
        #endregion

        [HttpGet]
        [Route("Form")]
        public IActionResult Form()
        {
            return View();
        }

        [HttpGet]
        [Route("Detail")]
        public IActionResult Detail()
        {
            return View();
        }

        protected Pagination GetPagination()
        {
            var pagination = new Pagination();
            var request = Request;

            var page = 1;
            var pageSize = 10;

            var pageQuery = request.Query["page"];
            var pageSizeQuery = request.Query["rows"];

            if (pageSizeQuery.Count == 0 || (pageQuery.Count > 0 && pageQuery[0] == "NaN"))
            {
                page = 1;
                pageSize = -1;
            }
            else {
                var pageIndexStr = request.Query["page"][0];
                var pageSizeStr = Request.Query["rows"][0];
                Int32.TryParse(pageIndexStr, out page);
                Int32.TryParse(pageSizeStr, out pageSize);
            }
            
            pagination.Page = page;
            pagination.PageSize = pageSize;

            return pagination;
        }




    }
}
